package lv.accenture.ex05;
import java.lang.Double;

public class RatNum implements Comparable {

       private final int numer;

       private final int denom;

       public RatNum(int n) {  
               numer = n;
               denom = 1;
       }

       public RatNum(int n, int d) {
               if (d == 0) {
                       numer = n;
                       denom = d;
               } else {
                       if (d < 0) {
                               n = n * (-1);
                               d = d * (-1);
                       }
                       if (n != 1) {
                               int devisor = gcd(n, d);
                               numer = n/devisor;
                               denom = d/devisor;              
                       } else {
                               numer = n;
                               denom = d;                                              
                       }
               }

       }

       public void checkRep() throws RuntimeException {
               // TODO
       }

       public boolean isNaN() {
               if (denom == 0) {
                       return true;
               } else {
                       return false;
               }              
       }

       public boolean isNegative() {
                       if ((numer < 0) && (!isNaN())) {
                               return true;
                       } else {
                               return false;
                       }
       }

       public boolean isPositive() {
                       if (((double) numer/denom > 0) || (isNaN())) {
                               return true;
                       } else {
                               return false;
                       }
       }

       public int compareTo(Object o) throws ClassCastException {
               RatNum rn = (RatNum) o;
               if (rn != null) {
                       if ((rn.isNaN()) && (this.isNaN())) {
                               return 0;
                       } else if ((rn.isNaN()) && (!this.isNaN())) {
                               return -1;
                       } else if ((!rn.isNaN()) && (this.isNaN())) {
                               return 1;
                       } else if (this.doubleValue() < rn.doubleValue()) {
                               return -1;
                       } else if (this.doubleValue() > rn.doubleValue()) {
                               return 1;
                       } else {
                               return 0;
                       }
               } else {
                       return 1;
               }
       }

       
       public double doubleValue() {

               double rn;
               if (denom > 0) {
                       rn = 1.0 * numer / denom;
               } else {
                       rn = Double.NaN;        
               }      
               
               return rn;
               
       }

       public String toString() {      
               if (isNaN()) {
                       return "NaN";
               } else if ((numer == denom) || (denom == 1))  {
                       return ""+numer;
               } else if (numer == 0) {
                       return "0";
               } else {
                       return this.numer + "/" + denom;
               }
       }

       public RatNum negate() {
               return new RatNum(numer*(-1),denom);
       }


       public RatNum add(RatNum arg) {
               if (arg != null) {
                       int result_n;
                       int result_d;
                       if (denom == arg.denom) {                      
                               result_n = numer+arg.numer;    
                               result_d = denom;
                       } else {
                               result_n = numer*arg.denom + arg.numer*denom;
                               result_d = denom * arg.denom;
                       }

                       return new RatNum(result_n,result_d);                  
               } else {
                       return null;
               }
               
       }


       public RatNum sub(RatNum arg) {
               if (arg != null) {
                       int result_n;
                       int result_d;
                       if (denom == arg.denom) {                      
                               result_n = numer-arg.numer;    
                               result_d = denom;
                       } else {
                               result_n = numer*arg.denom - arg.numer*denom;
                               result_d = denom * arg.denom;
                       }
                       
                       RatNum result = new RatNum(result_n,result_d);
                       return result;                  
               } else {
                       return null;
               }


       }


       public RatNum mul(RatNum arg) {
               if (arg != null) {
                       return new RatNum(numer*arg.numer,denom*arg.denom);
               } else {
                       return null;
               }
       }


       public RatNum div(RatNum arg) {
               if (arg != null) {
                       if (arg.isNaN()) {
                               return new RatNum(numer*arg.denom,0);
                       } else {
                               return new RatNum(numer*arg.denom,denom*arg.numer);
                       }
               } else {
                       return null;
               }
       }


       private static int gcd(int a, int b) {
               if (b == 0)
                       return 0;
               while (b != 0) {
                       int tmp = b;
                       b = a % b;
                       a = tmp;
               }
               if (a > 0) {
                       return a;                      
               }
               else {
                       return -a;                      
               }
       }

       public int hashCode() {
               //TODO
               return 0;
       }

       public boolean equals(Object obj) {
               RatNum obj1 = (RatNum) obj;
                       
               if ((this.isNaN()) && (obj1.isNaN())) {
                       return true;
               } else {
                       if ((this.numer == obj1.numer) && (this.denom == obj1.denom)) {
                               return true;
                       } else {
                               return false;
                       }
               }                      
       
       }


       public static RatNum parse(String ratStr) {
               if (ratStr == "NaN") {
                       return new RatNum(-1, 0);
               } else if (!ratStr.contains("/")) {
                       return new RatNum(Integer.parseInt(ratStr));
               } else {
                       String[] ratStr1 = ratStr.split("/");
                       int n,d;
                               
                       n = Integer.parseInt(ratStr1[0]);
                       d = Integer.parseInt(ratStr1[1]);
                       return new RatNum(n,d);
               }
               
               
       }
}
